home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_gwu / adavio.c < prev    next >
C/C++ Source or Header  |  1996-01-30  |  12KB  |  353 lines

  1. /*
  2.    HELP ENGINE PARA GWADA
  3.  
  4.    Módulo ADAVIO.C
  5.    Rotinas específicas para escrita direta na memória de vídeo
  6.  
  7.    Trabalho de conclusao
  8.    Bacharelado em Informática
  9.  
  10.    Ulrich Peters
  11.    Rafael Presotto
  12.    Jerry Dressler
  13. */
  14.  
  15. #include "..\source\adavio.h"
  16. #include <dos.h>
  17. #include <stdlib.h>
  18. #include <stdarg.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21.  
  22. typedef VEL far * VPFAR;           /* pointer para memória de vídeo */
  23. typedef struct windes WINDES;      /* descritor de janela */
  24. typedef WINDES * WIPTR;            /* pointer para descritor */
  25.  
  26. #define VOFS(x,y) ( col_vis * ( y ) + ( x ) )
  27. #define VPOS(x,y) (VPFAR) ( vstart + VOFS( x, y ) )
  28. #define WINDESLEN ( sizeof(struct windes) )
  29. #define VELLEN    ( sizeof( VEL ) )
  30.  
  31. struct windes {                 /* Descritor de janela */
  32.     int  x1, y1,                /* Vértices da janela */
  33.      x2, y2,
  34.      curs, curz;            /* Posiçao do cursor antes da abertura */
  35.     VEL  *winmem;        /* Pointer para o buffer */
  36.    };
  37.  
  38. VPFAR vstart;                 /* ponteiro ao primeiro caractere na VRAM */
  39. int   vlinha,                 /* armazena a posicao atual do cursor */
  40.       vcoluna,
  41.       viewx1,                 /* canto superior esquerdo da janela */
  42.       viewy1,
  43.       viewx2,                 /* canto inferior direito da janela */
  44.       viewy2,
  45.       lin_vis = 25,           /* numero de linhas */
  46.       col_vis = 80,           /* numero de colunas */
  47.       winopen = 0;            /* numero de janelas abertas */
  48. char  vkarte,                 /* codigo do sistema de video */
  49.       color;                  /* é 1 se placa pode mostrar cores */
  50. WIPTR winptr;                 /* pointer para descritor de janela */
  51.  
  52. /* Funcao inicial, determina o sistema de video
  53.    e seta as variavel do modulo de video */
  54. void VioInit( void )
  55. {
  56.  static char vmode[] = {
  57.              MDA, CGA, 0, EGA, EGA_MONO, 0,
  58.              VGA_MONO,  VGA, 0, MCGA, MCGA_MONO,
  59.              MCGA
  60.                };
  61.  static char egamode[] = {
  62.               EGA, EGA, EGA_MONO,
  63.              };
  64.  
  65.  union REGS regs; /* registradores para chamada de interrupcao */
  66.  vkarte = 0xff;   /* ainda sem placa definida */
  67.  
  68.  /* Testar se é placa VGA ou MCGA */
  69.  regs.x.ax = 0x1a00;
  70.  int86(0x10, ®s, ®s);
  71.  if ( regs.h.al == 0x1a )  /* VGA ou MCGA? */
  72.   {                        /* sim */
  73.    vkarte = vmode[ regs.h.bl-1 ];
  74.    color = (char) !( vkarte==MDA || vkarte==EGA_MONO );
  75.   }
  76.  else                      /* nao */
  77.   {
  78.    regs.h.ah = 0x12;       /* testar se é EGA */
  79.    regs.h.bl = 0x10;
  80.    int86(0x10, ®s, ®s);
  81.    if ( regs.h.bl != 0x10 )
  82.     {                      /* é sim */
  83.      vkarte = egamode[ (regs.h.cl >> 1) % 3 ];
  84.      color = (char) ( vkarte != EGA_MONO );
  85.     }
  86.   }
  87.  
  88.  /* definir ponteiro para memoria de video */
  89.  regs.h.ah = 15;
  90.  int86(0x10, ®s, ®s); /* determinar modo atual de video */
  91.  vstart = (VPFAR) MK_FP((regs.h.al!=7) ? 0xb800 : 0xb000, 0);
  92.  if ( vkarte == 0xff )      /* placa nao é EGA, VGA nem MCGA? */
  93.   {                         /* nao */
  94.    color = (char) ( regs.h.al != 7 );
  95.    vkarte = (char) (( color ) ? CGA : MDA);
  96.   }
  97.  else                       /* é, determinar numero de linhas */
  98.   lin_vis = *((char far *) MK_FP( 0x40, 0x84 )) + 1;
  99.  if ( regs.h.al==0 || regs.h.al==2 )
  100.   color = 0;                /* monitor colorido em modo P/B */
  101.  col_vis = *((char far *) MK_FP( 0x40, 0x4a ));  /* colunas */
  102.  
  103.  regs.h.ah = 5;             /* definir pagina de video atual = 0 */
  104.  regs.h.al = 0;
  105.  int86(0x10, ®s, ®s);
  106.  
  107.  regs.h.ah = 3;             /* determinar posicao do cursor */
  108.  regs.h.bh = 0;
  109.  int86(0x10, ®s, ®s);
  110.  vlinha = regs.h.dh;
  111.  vcoluna = regs.h.dl;
  112.  VioSetView(0, 0, col_vis-1, lin_vis-1);
  113.  winptr = (WIPTR) malloc( 1 );
  114. }
  115.  
  116. /* Salva as coordenadas da janela atual */
  117. void VioSetView( int x1, int y1, int x2, int y2 )
  118. {
  119.  viewx1 = x1;  /* anotar coordenadas */
  120.  viewy1 = y1;
  121.  viewx2 = x2;
  122.  viewy2 = y2;
  123. }
  124.  
  125. /* Copia uma janela da tela para um buffer */
  126. void VioGet( int x1, int y1, int x2, int y2, VEL far * bptr )
  127. {
  128.  int      nbytes;  /* numero de bytes a copiar por linha */
  129.  VPFAR    vioptr;  /* ponteiro a memoria de video */
  130.  
  131.  nbytes = ( x2 - x1 + 1 ) * VELLEN; /* bytes por linha */
  132.  for ( ; y1 <= y2; ++y1 )
  133.   {
  134.    vioptr = VPOS(x1, y1); /* apontar para o primeiro byte da linha */
  135.    MOVE( vioptr, bptr, nbytes);
  136.    (char far *) bptr += nbytes;
  137.   }
  138. }
  139.  
  140. /* Coloca um buffer de volta na tela
  141.    (restaura uma janela fechada)     */
  142. void VioPut( int x1, int y1, int x2, int y2, VEL far * bptr )
  143. {
  144.  int      nbytes;  /* numero de bytes a copiar por linha */
  145.  VPFAR    vioptr;  /* ponteiro a memoria de video */
  146.  
  147.  nbytes = ( x2 - x1 + 1 ) * VELLEN;
  148.  for ( ; y1 <= y2; ++y1 )
  149.   {
  150.    vioptr = VPOS(x1, y1);
  151.    MOVE( bptr, vioptr, nbytes);
  152.    (char far *) bptr += nbytes;
  153.   }
  154. }
  155.  
  156. /* Abre uma janela na tela, salva texto "abaixo" desta regiao */
  157. int VioWinOpen( int x1, int y1, int x2, int y2 )
  158. {
  159.  VEL * bptr; /* buffer */
  160.  WIPTR wptr; /* vetor com descritores de janela */
  161.  
  162.  /* alocar buffer */
  163.  if ( (bptr = (VEL *) malloc(BUFLEN( x1, y1, x2, y2 ))) != (VEL *) 0 )
  164.   {
  165.    wptr = (WIPTR) realloc(winptr, WINDESLEN * (winopen+1));
  166.    if ( wptr )
  167.     {
  168.      winptr = wptr; /* endereco novo do vetor */
  169.      (wptr += winopen)->x1 = x1; /* anotar coordenadas */
  170.      wptr->x2 = x2;
  171.      wptr->y1 = y1;
  172.      wptr->y2 = y2;
  173.      wptr->curs = vcoluna;
  174.      wptr->curz = vlinha; /* salvar tambem a posicao do cursor na janela */
  175.      VioGet( x1, y1, x2, y2, wptr->winmem = bptr );
  176.      ++winopen;
  177.      return 1;
  178.     }
  179.    else            /* sem memoria para vetor */
  180.     {
  181.      free( bptr ); /* liberar buffer */
  182.      return 0;     /* erro */
  183.     }
  184.   }
  185.  else              /* faltou espaco para buffer */
  186.   return 0;
  187. }
  188.  
  189. /* Fecha a ultima janela aberta (inf. no vetor de janelas)
  190.    e restaura o conteudo anterior se redraw != 0 */
  191. void VioWinClose( int redraw )
  192.  
  193. {
  194.  WIPTR wptr; /* vetor dos descritores de janela */
  195.  
  196.  if (winopen) /* tem uma janela aberta? */
  197.   {
  198.    wptr = winptr + winopen - 1;
  199.    if ( redraw ) /* restaurar tela? */
  200.     {
  201.      VioPut( wptr->x1, wptr->y1, wptr->x2,
  202.          wptr->y2, wptr->winmem );
  203.      VioSetCursor( wptr->curs, wptr->curz ); /* cursor na posicao anterior */
  204.     }
  205.    free( (void *) wptr->winmem ); /* liberar descritor */
  206.    /* atualizar vetor dos descritores */
  207.    winptr = (WIPTR) realloc(winptr, WINDESLEN*(--winopen)+1);
  208.   }
  209. }
  210.  
  211. /* Leva o cursor a posicao (coluna,linha) por interrupcao
  212.    do BIOS ( é mais rapido que gotoxy() ) */
  213. void VioSetCursor( int coluna, int linha )
  214. {
  215.  union REGS regs;
  216.  
  217.  regs.h.ah = 2;  /* Set Cursor */
  218.  regs.h.bh = 0;  /* Pag de video 0 */
  219.  regs.h.dh = (char) (vlinha = linha);
  220.  regs.h.dl = (char) (vcoluna = coluna);
  221.  int86(0x10, ®s, ®s);
  222. }
  223.  
  224. /* Escreve diretamente na memoria de video o texto especificado por "string",
  225.    na posicao "coluna,linha" e na cor especificada por "cor".
  226.    O byte "cursor" define se o cursor deverá ser levado até a posicao nova */
  227. void VioPrint( int coluna, int linha, char cor,
  228.            char cursor, char * string )
  229. {
  230.  register VPFAR lptr;
  231.  int newpos;  /* posicao do cursor como offset */
  232.  
  233.  newpos = coluna + linha * col_vis;
  234.  lptr = VPOS(coluna, linha);
  235.  for ( ; *string ; ++newpos, ++lptr)
  236.   {
  237.    lptr->h.caractere = *(string++);
  238.    lptr->h.atributo = cor;
  239.   }
  240.  if ( cursor ) /* mostrar cursor na posicao atual? */
  241.   VioSetCursor( newpos % col_vis, newpos / col_vis );
  242. }
  243.  
  244. /* Fornece saida formatada diretamente na memoria de video,
  245.    usando a sintaxe de VioPrint */
  246. void VioPrintf( int coluna, int linha, char cor,
  247.         char cursor, char * string, ... )
  248. {
  249.  va_list parametros; /* lista de parametros para as marcos va_... */
  250.  char saida[255];    /* buffer para o string formatado */
  251.  
  252.  va_start( parametros, string );        /* processar parametros */
  253.  vsprintf( saida, string, parametros ); /* formatar string */
  254.  VioPrint( coluna, linha, cor, cursor, saida );
  255. }
  256.  
  257. /* Enche um buffer com num ocorrencias de caractere
  258.    sendo num < 133                 */
  259. char *VioStrep( char caractere, int num )
  260. {
  261.  static char buf[133];
  262.  memset( (void *) buf, caractere, num = ((num > 132) ? 132 : num) );
  263.  buf[num] = '\0'; /* terminar strin */
  264.  return buf;      /* retorna ponteiro ao string gerado */
  265. }
  266.  
  267. /* Encher uma regiao da tela (x1,y1,x2,y2) com um dado
  268.    caractere e uma cor fornecida */
  269. void VioFill( int x1, int y1, int x2, int y2, char caractere, char cor)
  270. {
  271.  char * line;
  272.  
  273.  line = VioStrep( caractere, x2-x1+1 ); /* montar a linha */
  274.  for ( ; y1 <= y2; ++y1)                /* laco para as linhas */
  275.   VioPrint( x1, y1, cor, 0, line );     /* fornecer linha */
  276. }
  277.  
  278. /* Montagem de uma moldura na tela, usada para delimitar uma janela
  279.    de dimensoes (x1,y1,x2,y2). Moldura especificada por "mold" e "cor" */
  280. void VioFrame( int x1, int y1, int x2, int y2, char mold, char cor )
  281. {
  282.  static char moldura[4][6] = { /* as diferentes molduras disponiveis */
  283.                  { '┌', '┐', '└', '┘', '│', '─' },
  284.                  { '╔', '╗', '╚', '╝', '║', '═' },
  285.                  { '█', '█', '█', '█', '█', '█' },
  286.                  { '▒', '▒', '▒', '▒', '▒', '▒' } };
  287.  int i, k;
  288.  char *strepbuf, /* buffer de strep */
  289.       vert;      /* linha vertical */
  290.  
  291.  VioPrintf( x1, y1, cor, 0, "%c", mold[moldura][ 0 ] );
  292.  VioPrint( x1+1, y1, cor, 0,
  293.   strepbuf = VioStrep( mold[moldura][ 5 ], x2-x1-1 ) );
  294.  VioPrintf( x2, y1, cor, 0, "%c", mold[moldura][ 1 ] );
  295.  for (vert = mold[moldura][ 4 ], i=y1+1, k=y2-1; i <= k; ++i)
  296.   {
  297.    VioPrintf( x1, i, cor, 0, "%c", vert );
  298.    VioPrintf( x2, i , cor, 0, "%c", vert );
  299.   }
  300.  VioPrintf( x1, y2, cor, 0, "%c", mold[moldura][ 2 ] );
  301.  VioPrint( x1+1, y2, cor, 0, strepbuf );
  302.  VioPrintf( x2, y2, cor, 0, "%c", mold[moldura][ 3 ] );
  303. }
  304.  
  305. /* Trocar o atributo de uma regiao da tela, sem alterar o texto mostrado
  306.    (usado para destacar os textos de titulos e desvios, bem como marcar
  307.    a barra de selecao */
  308. void VioColor(int x1, int y1, int x2, int y2, char cor)
  309. {
  310.  register VPFAR lptr;
  311.  int i, j;
  312.  
  313.  for (j=x2 - x1 + 1 ; y1 <= y2; ++y1)
  314.   { /* percorrer os caracteres */
  315.    for (lptr = VPOS(x1, y1), i = j; i ; --i)
  316.     (lptr++)->h.atributo = cor;   /* trocar o atributo */
  317.   }
  318. }
  319.  
  320. /* Gera uma sombra em regiao (x1,y1,x2,y2) da tela, trocando para isto
  321.    o atributo de video dos caracteres, ou se for monitor MDA/Hercules,
  322.    escreve caracteres pontilhados ░ */
  323. void VioSombra( int x1, int y1, int x2, int y2 )
  324. {
  325.  register VEL *lptr;
  326.  VEL          *bptr;
  327.  int          num;
  328.  char         attr; /* atributo atual do caractere */
  329.  
  330.  if ( color )  /* monito é colorido? */
  331.   {
  332.    num = ( x2 - x1 + 1 ) * ( y2 - y1 + 1);
  333.    /* copiar regiao video para buffer */
  334.    lptr = bptr = (VEL *) malloc( num * sizeof( VEL ) );
  335.    VioGet( x1, y1, x2, y2, (VEL far *) bptr );
  336.    /* trocar os atributos do buffer */
  337.    for ( ; num--; ++lptr )
  338.     {
  339.      if ( (attr=lptr->h.atributo) & 128 ) /* fundo hilight? */
  340.       attr &= ~128;                       /* desligar bit de intensidade */
  341.      else
  342.       attr &= 15;                         /* fundo preto */
  343.      if ( attr & 8 )                      /* foreground claro? */
  344.       attr &= ~8;                         /* escurecer foreground */
  345.      lptr->h.atributo = attr;             /* setar atributo novo */
  346.     }
  347.    /* copiar buffer de volta para a tela */
  348.    VioPut( x1, y1, x2, y2, (VEL far *) bptr );
  349.    free( (void *) bptr ); /* desalocar memoria */
  350.   }
  351.  else /* monitor monocromatico */
  352.   VioFill( x1, y1, x2, y2, '▒', 0x07);
  353. }